home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
kernel
/
dev
/
sun4.md
/
devGraphics.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-18
|
34KB
|
1,230 lines
/*
* devGraphics.c --
*
* This module provides frame buffer device support.
*
* Copyright 1989 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/sun4.md/devGraphics.c,v 1.12 91/10/18 01:21:04 dlong Exp $ SPRITE (Berkeley)";
#endif /* not lint */
#include "sprite.h"
#include "dev.h"
#include <sys/ioctl.h>
#include "devfb.h"
#include "fs.h"
#include "vmMach.h"
#include "rpc.h"
#include "stdio.h"
#include "sys/types.h"
#include "mon/eeprom.h"
#include "machMon.h"
#include "stdlib.h"
#include "string.h"
#include "bstring.h"
#include "alloca.h"
#define EEC_COLOR_TYPE_CG4 4 /* missing in mon/eeprom.h */
#define EEC_COLOR_TYPE_CG6 6 /* missing in mon/eeprom.h */
/*
* For BW2 frame buffer
*/
#ifdef sun3
#define BW2_FB ((Address) 0x0fe20000)
#elif sun4c
#define BW2_FB ((Address) NIL)
#elif sun4
#define BW2_FB ((Address) 0xffd40000)
#else
#define BW2_FB ((Address) NIL)
#endif /* sun3 */
/*
* For CG4 frame buffer
*/
#ifdef sun3
#define CG4_FB ((Address) 0x0fd00000)
#define CG4_CM ((Address) 0x0fe0e000)
#define CG4_OV ((Address) 0x0fe80000)
#define CG4_EN ((Address) 0x0fea0000)
#else
#define CG4_FB ((Address) NIL)
#define CG4_CM ((Address) NIL)
#define CG4_OV ((Address) NIL)
#define CG4_EN ((Address) NIL)
#endif /* sun3 */
/*
* For CG6 frame buffer
*/
#define CG6_FB ((Address) NIL)
#define CG6_CM ((Address) NIL)
/*
* CG3 frame buffer.
*/
#define CG3_FB ((Address) NIL)
#define CG3_CM ((Address) NIL)
typedef struct FBDevice {
FBType type;
FBInfo info;
FBCMap cmap;
} FBDevice;
/*
* Associates a string with each fb type so we can use a hack to look up
* the type per machine from a file rather than the prom...
*/
char *fbNames[FBTYPE_LASTPLUSONE] = {
"bwone",
"cgone",
"bwtwo",
"cgtwo",
"FBTYPE_SUN_GP2",
"FBTYPE_SUN_CG5",
"cgthree",
"FBTYPE_MEMCOLOR",
"cgfour",
"FBTYPE_NOTSUN1",
"FBTYPE_NOTSUN2",
"FBTYPE_NOTSUN3",
"cgsix",
"FBTYPE_SUNROP_COLOR",
"FBTYPE_SUNFB_VIDEO",
"FBTYPE_RESERVED5",
"FBTYPE_RESERVED4",
"FBTYPE_RESERVED3",
"FBTYPE_RESERVED2",
"FBTYPE_RESERVED1"
};
/*
* Brooktree DAC
*/
volatile struct colormap {
unsigned int addr; /* colormap address register */
unsigned int cmap; /* colormap data register */
unsigned int ctrl; /* control register */
unsigned int omap; /* overlay map data register */
} *fbCmap = (volatile struct colormap *) NIL;
/* Copy of colormap (for CG4 only!) */
static union {
unsigned char map[256][3]; /* reasonable way to access */
unsigned int raw[256*3/4]; /* unreasonable way used to load h/w */
} fbCmapCopy;
/*
* Addresses to know for the different frame buffers, overlay planes, etc.
*/
typedef struct FBAddr {
Address fb_buffer; /* kernel virtual address */
Address fb_overlay; /* offset? */
Address fb_enable; /* offset? */
Address fb_cmap; /* cmap */
} FBAddr;
/*
* Addresses for frame buffer, overlay and enable. This is in a separate
* array since it's different per machine type. I only have it for
* one machine type right now (sun4c).
*/
FBAddr fbaddrs[FBTYPE_LASTPLUSONE] = {
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* bw1 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* cg1 */
{BW2_FB, (Address) NIL, (Address) NIL, (Address) NIL}, /* bw2 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* cg2 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* gp2 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* cg5 */
{CG3_FB, (Address) NIL, (Address) NIL, CG3_CM}, /* cg3 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* ? */
{CG4_FB, CG4_OV, CG4_EN, CG4_CM}, /* cg4 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* cust. */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* cust. */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* cust. */
{CG6_FB, (Address) NIL, (Address) NIL, CG6_CM}, /* cg6 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* rop */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* video */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* res5 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* res4 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* res3 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL}, /* res2 */
{(Address) NIL, (Address) NIL, (Address) NIL, (Address) NIL} /* res1 */
};
/*
* For convenience we store info about the frame buffer types here. If we
* get the info from the prom, we overwrite the stuff here.
* Array indexed by fb_type, found in fb.h.
* An example of what would be overwritten is if we have a high resolution
* b&w screen, the info in the prom will give us
* {high resolution bw2, 1280, 1600, 1, 2, 256*1024}, (* bw2h *)
* instead of the regular bw2. Also, for cg3, we could have a second type:
* {cg3b, 768, 1024, -1, -1, -1} (* cg3 B *)
*/
/* type, height, width, depth, cmsize, size */
FBType fbarray[FBTYPE_LASTPLUSONE] = {
{FBTYPE_SUN1BW, -1, -1, -1, -1, -1}, /* bw1 */
{FBTYPE_SUN1COLOR, -1, -1, -1, -1, -1}, /* cg1 */
{FBTYPE_SUN2BW, 900, 1152, 1, 2, 128*1024}, /* bw2 */
{FBTYPE_SUN2COLOR, 900, 1152, 8, -1, -1}, /* cg2 */
{FBTYPE_SUN2GP, -1, -1, -1, -1, -1}, /* gp2 */
{FBTYPE_SUN5COLOR, -1, -1, -1, -1, -1}, /* cg5? |bw3? */
{FBTYPE_SUN3COLOR, 900, 1152, 8, 256, 1024*1024}, /* cg3 A */
{FBTYPE_MEMCOLOR, -1, -1, -1, -1, -1}, /* ? | bw4? */
{FBTYPE_SUN4COLOR, 900, 1152, 8, 256, 1024*1024}, /* cg4 */
{FBTYPE_NOTSUN1, -1, -1, -1, -1, -1}, /* customer */
{FBTYPE_NOTSUN2, -1, -1, -1, -1, -1}, /* customer */
{FBTYPE_NOTSUN3, -1, -1, -1, -1, -1}, /* customer */
{FBTYPE_SUNFAST_COLOR, 900, 1152, 8, 256, 1024*1024}, /* cg6=gx*/
{FBTYPE_SUNROP_COLOR, -1, -1, -1, -1, -1},
{FBTYPE_SUNFB_VIDEO, -1, -1, -1, -1, -1},
{FBTYPE_RESERVED5, -1, -1, -1, -1, -1}, /* don't use */
{FBTYPE_RESERVED4, -1, -1, -1, -1, -1}, /* don't use */
{FBTYPE_RESERVED3, -1, -1, -1, -1, -1}, /* don't use */
{FBTYPE_RESERVED2, -1, -1, -1, -1, -1}, /* don't use */
{FBTYPE_RESERVED1, -1, -1, -1, -1, -1} /* don't use */
};
/*
*
* Thorsten's notes for the old user-level fbio stuff:
*
*
* Brooktree DAC/colormap information
*
* Operation theory (really: guesses)
*
* The DAC has four byte size "ports" (cpu accessible registers) which have to
* be used to access the three internal register files with the 256 colormap
* RGB entries, a few control registers and 4 overlay RGB entries.
* To access a control register: write the register number (0-7?) into
* "addr" (see struct below), then write the value into "ctrl".
* To access a RGB entry: write the entry number (0-255 or 0-3) into "addr"
* then write the R, G and B values (in that order) into "cmap" or "omap".
* After the access, the "addr" is automatically incremented to allow quick
* updates of successive colormap entries.
*
* Now, this was the meat and here comes the spice:
* On the CG6 board, the ports are on (mod 4)=0 addresses and require
* longword accesses. This means the value has to go into bits 24-31 of
* an int which is then written to the chip. (Similarly for reading.)
* On the CG4 board, things are even better: the ports are on (mod 4)=3
* addresses and require longword accesses. The value can thus reside
* in the low 8 bits of an int. However, colormap RGB values behave
* wonderfully different: one longword write to "cmap" or "omap" is
* turned (by the hardware) into four byte writes to the chip, the
* top byte first, the bottom one last. (Dunno 'bout reads.) This means
* that one write to "cmap" or "omap" writes 4/3 colormap RGB entries.
* For example, writing a "1" into "addr" and 0x01020304 into "cmap" will
* set green and blue of color 1 to 0x01 and 0x02 resp. and will set
* red and green of color 2 to 0x03 and 0x04 resp.!
*
* Note: I didn't build these suckers, I just poked at them and guessed
* the behaviour, and I might be wrong...
* Thorsten von Eicken, 2/19/90
*/
/*
* forward declarations for internal routines
*/
#ifdef sun4c
static int CheckFBNode _ARGS_((unsigned int node, char *name));
static int GetFBType _ARGS_((void));
#endif
static ReturnStatus PutCmap _ARGS_((int whichFb, FBCMap *cmap));
static ReturnStatus GetCmap _ARGS_((int whichFb, FBCMap *cmap));
static ReturnStatus SVideo _ARGS_((int whichFb, int *statePtr));
static ReturnStatus GVideo _ARGS_((int whichFb, int *statePtr));
static ReturnStatus InitCmap _ARGS_((FBDevice *devPtr));
/*
*----------------------------------------------------------------------
*
* DevFBOpen --
*
* Open the system frame buffer device.
*
* Results:
* SUCCESS - the device was opened.
* FAILURE - something went wrong.
*
* Side effects:
* The device is opened.
*
*----------------------------------------------------------------------
*/
/*ARGSUSED*/
ReturnStatus
DevFBOpen(devicePtr, useFlags, token, flagsPtr)
Fs_Device *devicePtr; /* Device info, unit number, etc. */
int useFlags; /* Flags from the stream being opened. */
Fs_NotifyToken token; /* Call-back token for input, unused here. */
int *flagsPtr; /* OUT: Device open flags. */
{
FBDevice *devPtr;
#ifdef sun4c
extern int GetFBType();
#endif
FBType *typePtr;
int machArch;
int machType;
int whichFb = -1;
#ifndef sun4c
struct eeprom *eeprom;
struct eed_conf *eeconf;
int i;
#endif
devPtr = (FBDevice *) malloc(sizeof (FBDevice));
bzero((char *) devPtr, sizeof (FBDevice));
machArch = Mach_GetMachineArch();
machType = Mach_GetMachineType();
devPtr->type.fb_type = -1;
#ifdef sun4c
whichFb = GetFBType();
if (whichFb == -1) {
whichFb = FBTYPE_SUN2BW;
}
#else
switch (machArch) {
case SYS_SUN4:
case SYS_SUN3:
eeprom = (struct eeprom *)EEPROM_BASE;
eeconf = &(eeprom->ee_diag.eed_conf[0]);
for (i = 0; i < MAX_SLOTS; i++, eeconf++) {
#ifdef FOOBAR
printf("card type %d\n", eeconf->eec_un.eec_type);
#endif FOOBAR
/* end of card cage? */
if (eeconf->eec_un.eec_type == EEC_TYPE_END) {
break;
}
/* color display? */
if (eeconf->eec_un.eec_type == EEC_TYPE_COLOR) {
#ifdef FOOBAR
printf("\tcolor type %d\n",
eeconf->eec_un.eec_color.eec_color_type);
#endif FOOBAR
switch (eeconf->eec_un.eec_color.eec_color_type) {
case EEC_COLOR_TYPE_CG4:
whichFb = FBTYPE_SUN4COLOR;
break;
case EEC_COLOR_TYPE_CG6:
whichFb = FBTYPE_SUNFAST_COLOR;
break;
default:
; /* just ignore... */
}
}
/* b/w display? (note: give preference to color) */
if (whichFb == -1 && eeconf->eec_un.eec_type == EEC_TYPE_BW) {
if (eeprom->ee_diag.eed_scrsize == EED_SCR_1600X1280) {
whichFb = FBTYPE_SUN2BW;
fbarray[whichFb].fb_height = 1280;
fbarray[whichFb].fb_width = 1600;
fbarray[whichFb].fb_size = 256 * 1024;
} else {
whichFb = FBTYPE_SUN2BW;
}
}
}
/* assume b/w as default */
if (whichFb == -1) {
whichFb = FBTYPE_SUN2BW;
}
if ((whichFb == FBTYPE_SUN2BW) &&
(eeprom->ee_diag.eed_scrsize == EED_SCR_1600X1280)) {
whichFb = FBTYPE_SUN2BW;
fbarray[whichFb].fb_height = 1280;
fbarray[whichFb].fb_width = 1600;
fbarray[whichFb].fb_size = 256 * 1024;
}
break;
case SYS_DS3100:
printf("Can't do FB stuff for ds3100's yet.\n");
return FAILURE;
default:
printf("FB stuff won't handle this machine type yet.\n");
return FAILURE;
}
#endif /* sun4c */
if (whichFb < 0 || whichFb >= FBTYPE_LASTPLUSONE) {
printf("FB type is out of range.\n");
return FAILURE;
}
typePtr = &fbarray[whichFb];
devPtr->type.fb_type = typePtr->fb_type;
devicePtr->data = (ClientData) devPtr;
return SUCCESS;
}
/*
*----------------------------------------------------------------------
*
* DevFBIOControl --
*
* Perform device-specific functions with the frame buffer.
*
* Results:
* GEN_NOT_IMPLEMENTED if io control not supported. GEN_INVALID_ARG
* if something else went wrong. SUCCESS otherwise, with the type
* of the frame buffer described in the out-going buffer.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
ReturnStatus
DevFBIOControl(devicePtr, ioctlPtr, replyPtr)
Fs_Device *devicePtr; /* Handle for device. */
Fs_IOCParam *ioctlPtr; /* Standard I/O Control parameter block. */
Fs_IOReply *replyPtr; /* Size of outBuffer and returned signal. */
{
FBDevice *devPtr;
FBType *typePtr;
devPtr = (FBDevice *) (devicePtr->data);
switch (ioctlPtr->command) {
case FBIOGTYPE:
if (ioctlPtr->outBufSize < sizeof (FBType)) {
printf("Bad outbuf size.\n");
return GEN_INVALID_ARG;
}
if (devPtr->type.fb_type < 0 ||
devPtr->type.fb_type >= FBTYPE_LASTPLUSONE) {
printf("fbtype was bad.\n");
return FAILURE;
}
typePtr = &(fbarray[devPtr->type.fb_type]);
/* copy to outbuf */
devPtr->type.fb_height = typePtr->fb_height;
devPtr->type.fb_width = typePtr->fb_width;
devPtr->type.fb_depth = typePtr->fb_depth;
devPtr->type.fb_cmsize = typePtr->fb_cmsize;
devPtr->type.fb_size = typePtr->fb_size;
bcopy((char *) &(devPtr->type), (char *) ioctlPtr->outBuffer,
sizeof (FBType));
break;
#ifdef NOTDEF
/*
* Does this ioctl really exist? Is it used?
*/
case FBIOGINFO:
if (ioctlPtr->outBufSize < sizeof (FBInfo)) {
return GEN_INVALID_ARG;
}
devPtr->info.fb_physaddr = XX;
devPtr->info.fb_hwwidth = XX;
devPtr->info.fb_hwheight = XX;
devPtr->info.fb_addrdelta = XX;
devPtr->info.fb_ropaddr = XX;
devPtr->info.fb_unit = XX;
break;
#endif /* NOTDEF */
case FBIOPUTCMAP:
if (ioctlPtr->inBufSize < sizeof (FBCMap)) {
printf("Bad inbuf size.\n");
return GEN_INVALID_ARG;
}
if (devPtr->type.fb_type < 0 ||
devPtr->type.fb_type >= FBTYPE_LASTPLUSONE) {
printf("fbtype was bad.\n");
return FAILURE;
}
if (fbCmap == (struct colormap *) NIL) {
if (InitCmap(devPtr) != SUCCESS) {
printf("Couldn't initialize colormap.\n");
return FAILURE;
}
}
if (PutCmap(devPtr->type.fb_type,
(FBCMap *) ioctlPtr->inBuffer) != SUCCESS) {
return FAILURE;
}
break;
case FBIOGETCMAP:
if (ioctlPtr->outBufSize < sizeof (FBCMap)) {
printf("Bad outbuf size.\n");
return GEN_INVALID_ARG;
}
if (devPtr->type.fb_type < 0 ||
devPtr->type.fb_type >= FBTYPE_LASTPLUSONE) {
printf("fbtype was bad.\n");
return FAILURE;
}
if (fbCmap == (struct colormap *) NIL) {
if (InitCmap(devPtr) != SUCCESS) {
printf("Couldn't initialize colormap.\n");
return FAILURE;
}
}
if (GetCmap(devPtr->type.fb_type,
(FBCMap *) ioctlPtr->outBuffer) != SUCCESS) {
return FAILURE;
}
break;
case FBIOSVIDEO:
if (ioctlPtr->inBufSize < sizeof (int)) {
printf("Bad inbuf size.\n");
return GEN_INVALID_ARG;
}
if (devPtr->type.fb_type < 0 ||
devPtr->type.fb_type >= FBTYPE_LASTPLUSONE) {
printf("fbtype was bad.\n");
return FAILURE;
}
/*
* If the display is a color display, initialize the color map first.
*/
switch (devPtr->type.fb_type) {
case FBTYPE_SUN1COLOR:
case FBTYPE_SUN2COLOR:
case FBTYPE_SUN2GP: /* color? */
case FBTYPE_SUN5COLOR:
case FBTYPE_SUN3COLOR:
case FBTYPE_MEMCOLOR:
case FBTYPE_SUN4COLOR:
case FBTYPE_SUNFAST_COLOR:
case FBTYPE_SUNROP_COLOR:
case FBTYPE_SUNFB_VIDEO: /* color? */
if (fbCmap == (struct colormap *) NIL) {
if (InitCmap(devPtr) != SUCCESS) {
printf("Couldn't initialize colormap.\n");
return FAILURE;
}
}
break;
default:
/* Do nothing. */
break;
}
if (SVideo(devPtr->type.fb_type,
(int *) ioctlPtr->inBuffer) != SUCCESS) {
return FAILURE;
}
break;
case FBIOGVIDEO:
if (ioctlPtr->outBufSize < sizeof (int)) {
printf("Bad outbuf size.\n");
return GEN_INVALID_ARG;
}
if (devPtr->type.fb_type < 0 ||
devPtr->type.fb_type >= FBTYPE_LASTPLUSONE) {
printf("fbtype was bad.\n");
return FAILURE;
}
/*
* If the display is a color display, initialize the color map first.
*/
switch (devPtr->type.fb_type) {
case FBTYPE_SUN1COLOR:
case FBTYPE_SUN2COLOR:
case FBTYPE_SUN2GP: /* color? */
case FBTYPE_SUN5COLOR:
case FBTYPE_SUN3COLOR:
case FBTYPE_MEMCOLOR:
case FBTYPE_SUN4COLOR:
case FBTYPE_SUNFAST_COLOR:
case FBTYPE_SUNROP_COLOR:
case FBTYPE_SUNFB_VIDEO: /* color? */
if (fbCmap == (struct colormap *) NIL) {
if (InitCmap(devPtr) != SUCCESS) {
printf("Couldn't initialize colormap.\n");
return FAILURE;
}
}
break;
default:
/* Do nothing. */
break;
}
if (GVideo(devPtr->type.fb_type,
(int *) ioctlPtr->outBuffer) != SUCCESS) {
return FAILURE;
}
break;
case FBIOSATTR:
case FBIOGATTR:
#ifdef NOTDEF
case FBIOGVERTICAL:
#endif NOTDEF
printf("Not implemented.\n");
return GEN_NOT_IMPLEMENTED;
default:
printf("Default: invalid arg.\n");
return GEN_INVALID_ARG;
}
return SUCCESS;
}
/*
*----------------------------------------------------------------------
*
* DevFBClose --
*
* Close the frame buffer.
*
* Results:
* SUCCESS - always returned.
*
* Side effects:
* The frame buffer is "closed".
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
ReturnStatus
DevFBClose(devicePtr, useFlags, openCount, writerCount)
Fs_Device *devicePtr; /* Information about device. */
int useFlags; /* Indicates whether stream being
* closed was for reading and/or
* writing: OR'ed combination of
* FS_READ and FS_WRITE. */
int openCount; /* # of times this particular stream
* is still open. */
int writerCount; /* # of times this particular stream
* is still open for writing. */
{
if ((openCount == 0) && (devicePtr->data != (ClientData) NIL)) {
free((Address) devicePtr->data);
}
return SUCCESS;
}
char searchBuffer[1024];
/*
*----------------------------------------------------------------------
*
* CheckFBNode --
*
* Check the frame buffer node for the information we need.
*
* Results:
* The frame buffer type.
*
* Side effects:
* Info about the device from the prom gets put into the fb table.
*
*----------------------------------------------------------------------
*/
#ifdef sun4c
static int
CheckFBNode(node, name)
unsigned int node;
char *name;
{
int length = 0;
struct config_ops *configPtr;
int i;
int whichFb;
configPtr = romVectorPtr->v_config_ops;
#ifndef CLEAN
length = configPtr->devr_getproplen(node, "device_type");
if (length <= 0) {
#ifdef DEBUG
printf("No device_type attribute found for %s.\n", name);
#endif /* DEBUG */
} else {
configPtr->devr_getprop(node, "device_type", searchBuffer);
if (strcmp(searchBuffer, "display") != 0) {
#ifdef DEBUG
printf("device_type for %s was not \"display\".\n", name);
#endif /* DEBUG */
return 0;
}
}
#endif
for (i = 0; i < FBTYPE_LASTPLUSONE; i++) {
if (strcmp(name, fbNames[i]) == 0) {
whichFb = i;
/* fill it in */
length = configPtr->devr_getproplen(node, "height");
if (length <= 0) {
printf("No height found for frame buffer in prom.\n");
} else {
configPtr->devr_getprop(node, "height", searchBuffer);
if (fbarray[i].fb_height != *(int *) searchBuffer) {
#ifdef DEBUG
printf("Updating height for %s to 0x%x.\n",
fbNames[whichFb], *(int *) searchBuffer);
#endif /* DEBUG */
fbarray[i].fb_height = *(int *) searchBuffer;
}
}
length = configPtr->devr_getproplen(node, "width");
if (length <= 0) {
printf("No width found for frame buffer in prom.\n");
} else {
configPtr->devr_getprop(node, "width", searchBuffer);
if (fbarray[i].fb_width != *(int *) searchBuffer) {
#ifdef DEBUG
printf("Updating width for %s to 0x%x.\n",
fbNames[whichFb], *(int *) searchBuffer);
#endif /* DEBUG */
fbarray[i].fb_width = *(int *) searchBuffer;
}
}
length = configPtr->devr_getproplen(node, "depth");
if (length <= 0) {
printf("No depth found for frame buffer in prom.\n");
} else {
configPtr->devr_getprop(node, "depth", searchBuffer);
if (fbarray[i].fb_depth != *(int *) searchBuffer) {
#ifdef DEBUG
printf("Updating depth for %s to 0x%x.\n",
fbNames[whichFb], *(int *) searchBuffer);
#endif /* DEBUG */
fbarray[i].fb_depth = *(int *) searchBuffer;
}
}
length = configPtr->devr_getproplen(node, "address");
if (length <= 0) {
printf("No address found for frame buffer in prom.\n");
} else {
configPtr->devr_getprop(node, "address", searchBuffer);
if (fbaddrs[i].fb_buffer !=
(Address) (*(int *) searchBuffer)) {
#ifdef DEBUG
printf("Updating address for %s to 0x%x.\n",
fbNames[whichFb], *(int *) searchBuffer);
#endif /* DEBUG */
fbaddrs[i].fb_buffer =
(Address) (*(int *) searchBuffer);
}
}
length = configPtr->devr_getproplen(node, "reg");
if (length <= 0) {
printf("No registers found for frame buffer in prom.\n");
} else {
MachDevReg *regs;
char *phys, *virt;
int nregs, reg_offset;
regs = (MachDevReg *)alloca(length);
nregs = length / sizeof(MachDevReg);
configPtr->devr_getprop(node, "reg", regs);
switch (whichFb) {
case FBTYPE_SUNFAST_COLOR:
reg_offset = 0x200000;
break;
case FBTYPE_SUN2BW:
case FBTYPE_SUN3COLOR:
default:
reg_offset = 0x400000;
}
if (romVectorPtr->v_romvec_version < 2
&& regs[0].addr >= (Address)SBUS_BASE
&& regs[0].bustype == 1) { /* old style */
phys = regs[0].addr + reg_offset;
} else { /* new style */
phys = regs[0].addr + SBUS_BASE +
regs[0].bustype * SBUS_SIZE +
reg_offset;
}
virt = VmMach_MapInDevice(phys, 1);
#if 0
if (fbarray[i].fb_depth > 1 && fbaddrs[i].fb_cmap != virt) {
#else
if (fbaddrs[i].fb_cmap != virt) {
#endif
#ifdef DEBUG
printf("Updating colormap address for %s to 0x%x.\n",
fbNames[whichFb], virt);
#endif /* DEBUG */
fbaddrs[i].fb_cmap = virt;
}
}
return whichFb;
}
}
return -1;
}
#endif /* sun4c */
/*
*----------------------------------------------------------------------
*
* GetFBType --
*
* Routine the find the frame buffer attributes from the PROM.
*
* Results:
* Integer representing frame buffer type.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
#ifdef sun4c
static int
GetFBType()
{
struct config_ops *configPtr;
unsigned int root, fb_node;
int size;
char *fb_type;
configPtr = romVectorPtr->v_config_ops;
/*
* Find a frame buffer type: First get the root node id of the tree of
* devices in the prom. Then retrieve a pointer to the active frame
* buffer node. Call CheckFBNode to pull all the required info from
* the PROM.
*/
root = configPtr->devr_next(0);
configPtr->devr_getprop(root, "fb", &fb_node);
size = configPtr->devr_getproplen(fb_node, "name");
fb_type = (char *)alloca(size);
configPtr->devr_getprop(fb_node, "name", fb_type);
return CheckFBNode(fb_node, fb_type);
}
#endif /* sun4c */
/*
*----------------------------------------------------------------------
*
* DevFBMMap --
*
* Map a device into user space.
*
* Results:
* SUCCESS or FAILURE.
*
* Side effects:
* Device area made accessible to user.
*
*----------------------------------------------------------------------
*/
/*ARGSUSED*/
ReturnStatus
DevFBMMap(devicePtr, startAddr, length, offset, newAddrPtr)
Fs_Device *devicePtr;
Address startAddr;
int length;
int offset;
Address *newAddrPtr;
{
FBDevice *devPtr;
Address kernelAddr; /* Virtual address in kernel of device. */
Address kernelAlignedAddr; /* Aligned virtual addr in kernel. */
int numBytes;
ReturnStatus status;
devPtr = (FBDevice *) (devicePtr->data);
kernelAddr = (Address) (fbaddrs[devPtr->type.fb_type].fb_buffer);
if (kernelAddr == (Address) NIL) {
printf("FB device has no kernel address.\n");
return FAILURE;
}
/*
* Must align user address forwards rather than backwards. They must
* have allocated an extra segment.
*/
kernelAlignedAddr = (Address)
(((unsigned int)kernelAddr) & ~(VMMACH_SEG_SIZE - 1));
numBytes = ((unsigned int)((kernelAddr + length) - kernelAlignedAddr) +
(VMMACH_SEG_SIZE - 1)) & ~(VMMACH_SEG_SIZE - 1);
status = VmMach_IntMapKernelIntoUser((unsigned int) kernelAlignedAddr,
numBytes, (unsigned int) startAddr, newAddrPtr);
if (status != SUCCESS) {
return status;
}
*newAddrPtr += (((unsigned int)kernelAddr) % VMMACH_SEG_SIZE);
#ifdef DEBUG
printf("Real VA would be 0x%x\n", *newAddrPtr);
#endif /* DEBUG */
return SUCCESS;
}
/*
*----------------------------------------------------------------------
*
* PutCmap --
*
* Update the hardware colormap.
*
* Results:
* SUCCESS or FAILURE.
*
* Side effects:
* Memory updated.
*
*----------------------------------------------------------------------
*/
static ReturnStatus
PutCmap(whichFb, cmap)
int whichFb;
FBCMap *cmap;
{
unsigned char *uPtr;
unsigned int *iPtr;
int c;
int index = cmap->index;
int count = cmap->count;
unsigned char *rmap = cmap->red;
unsigned char *gmap = cmap->green;
unsigned char *bmap = cmap->blue;
if(index < 0) {
printf("cmap index was < 0.\n");
return FAILURE;
}
/* Handle colors 0..255 */
if (index >= 0 && index < 256) {
if (index+count > 256) {
count = 256 - index;
}
if (whichFb == FBTYPE_SUN4COLOR || whichFb == FBTYPE_SUN3COLOR) {
/* update the memory copy */
uPtr = &fbCmapCopy.map[index][0];
for (c = count; c != 0; --c) {
*uPtr++ = *rmap++;
*uPtr++ = *gmap++;
*uPtr++ = *bmap++;
}
/* update DAC: weird 4/3 entries per word mapping */
#define D4M3(x) ((((x)>>2)<<1) + ((x)>>2)) /* (x/4)*3 */
#define D4M4(x) ((x)&~0x3) /* (x/4)*4 */
iPtr = &fbCmapCopy.raw[D4M3(index)];
fbCmap->addr = D4M4(index);
for (c = D4M3(index+count-1) - D4M3(index) + 3; c != 0; --c) {
fbCmap->cmap = *iPtr++;
}
} else { /* FBTYPE_SUNFAST_COLOR */
/* update the chip */
fbCmap->addr = index << 24;
for (c = count; c != 0; --c) {
fbCmap->cmap = (unsigned int)(*rmap++) << 24;
fbCmap->cmap = (unsigned int)(*gmap++) << 24;
fbCmap->cmap = (unsigned int)(*bmap++) << 24;
}
}
/* What's left? */
index += count;
count = cmap->count-count;
}
/* Any overlay color changes? */
if (index >= 256 && count > 0) {
/******* dunno how to do that */
}
return SUCCESS;
}
/*
*----------------------------------------------------------------------
*
* GetCmap --
*
* Return the hardware colormap.
*
* Results:
* SUCCESS or FAILURE.
*
* Side effects:
* Memory updated.
*
*----------------------------------------------------------------------
*/
static ReturnStatus
GetCmap(whichFb, cmap)
int whichFb;
FBCMap *cmap;
{
unsigned char *uPtr;
int c;
int index = cmap->index;
int count = cmap->count;
unsigned char *rmap = cmap->red;
unsigned char *gmap = cmap->green;
unsigned char *bmap = cmap->blue;
if(index < 0) {
return FAILURE;
}
/* Handle colors 0..255 */
if(index >= 0 && index < 256) {
if(index+count > 256) {
count = 256 - index;
}
if (whichFb == FBTYPE_SUN4COLOR || whichFb == FBTYPE_SUN3COLOR) {
/* copy from the memory copy */
uPtr = &fbCmapCopy.map[index][0];
c = count;
while(c--) {
*rmap++ = *uPtr++;
*gmap++ = *uPtr++;
*bmap++ = *uPtr++;
}
} else { /* FBTYPE_SUNFAST_COLOR */
/* get it from the chip */
fbCmap->addr = index << 24;
c = count;
while(c--) {
*rmap++ = (unsigned char)(fbCmap->cmap >> 24);
*gmap++ = (unsigned char)(fbCmap->cmap >> 24);
*bmap++ = (unsigned char)(fbCmap->cmap >> 24);
}
}
/* What's left? */
index += count;
count = cmap->count-count;
}
/* Any overlay color requested? */
if(index >= 256 && count > 0) {
/******* dunno how to do that */
}
return SUCCESS;
}
/*
*----------------------------------------------------------------------
*
* SVideo --
*
* Turn on or off the video.
*
* Results:
* SUCCESS or FAILURE.
*
* Side effects:
* Video turned on or off.
*
*----------------------------------------------------------------------
*/
static ReturnStatus
SVideo(whichFb, statePtr)
int whichFb;
int *statePtr;
{
int onOff;
onOff = *statePtr;
switch (whichFb) {
case FBTYPE_SUN2BW:
case FBTYPE_SUN3COLOR:
/* this works for some color frame buffers too. -dl */
if (fbaddrs[whichFb].fb_cmap != (void *)NIL) {
if (onOff) {
*(unsigned char *)(fbaddrs[whichFb].fb_cmap + 0x10) |= 0x40;
} else {
*(unsigned char *)(fbaddrs[whichFb].fb_cmap + 0x10) &= ~0x40;
}
}
return SUCCESS;
case FBTYPE_SUN4COLOR:
case FBTYPE_SUNFAST_COLOR:
/* get colormap access */
if(fbCmap == (struct colormap *) NIL) {
printf("Colormap not yet set.\n");
return FAILURE;
}
/* Twiddle command registers to turn video off */
if (onOff) {
onOff = ~0;
}
if(whichFb == FBTYPE_SUNFAST_COLOR) {
fbCmap->addr = 0x04 << 24; /* read mask */
fbCmap->ctrl = onOff; /* color planes */
} else {
/* overlay off for blanking */
fbCmap->addr = 0x06; /* command reg */
fbCmap->ctrl = 0x70|(onOff&3); /* overlay plane */
/* read mask off for blanking */
fbCmap->addr = 0x04; /* read mask */
fbCmap->ctrl = onOff; /* color planes */
if(!onOff) {
/* color 0 -> black for blanking */
fbCmap->addr = 0x00;
fbCmap->cmap = 0x00000000;
} else {
/* restore colors */
fbCmap->addr = 0x00;
fbCmap->cmap = fbCmapCopy.raw[0];
fbCmap->cmap = fbCmapCopy.raw[1];
fbCmap->cmap = fbCmapCopy.raw[2];
}
}
return SUCCESS;
default:
return FAILURE;
}
}
/*
*----------------------------------------------------------------------
*
* GVideo --
*
* Get the on/off status of the video.
*
* Results:
* SUCCESS or FAILURE.
*
* Side effects:
* Video status returned in out parameter.
*
*----------------------------------------------------------------------
*/
static ReturnStatus
GVideo(whichFb, statePtr)
int whichFb;
int *statePtr;
{
int rmask;
switch (whichFb) {
case FBTYPE_SUN2BW:
case FBTYPE_SUN3COLOR:
if (fbaddrs[whichFb].fb_cmap != (void *)NIL) {
rmask = *(unsigned char *)(fbaddrs[whichFb].fb_cmap + 0x10);
*statePtr = (rmask & 0x40) ? 1 : 0;
}
return SUCCESS;
case FBTYPE_SUN4COLOR:
case FBTYPE_SUNFAST_COLOR:
/* get colormap access */
if(fbCmap == (struct colormap *) NIL) {
printf("Colormap not yet set.\n");
return FAILURE;
}
/* Look hard at the control registers */
if(whichFb == FBTYPE_SUNFAST_COLOR) {
fbCmap->addr = 0x04 << 24; /* read mask */
rmask = fbCmap->ctrl >> 24; /* color planes */
} else {
fbCmap->addr = 0x04; /* read mask */
rmask = fbCmap->ctrl; /* color planes */
}
*statePtr = (rmask & 0xff) ? 1 : 0;
break;
default:
return FAILURE;
}
return SUCCESS;
}
/*
*----------------------------------------------------------------------
*
* InitCmap --
*
* Initialize the colormap.
*
* Results:
* SUCCESS or FAILURE.
*
* Side effects:
* Colormap data structures initialized.
*
*----------------------------------------------------------------------
*/
static ReturnStatus
InitCmap(devPtr)
FBDevice *devPtr;
{
int c;
int whichFb;
whichFb = devPtr->type.fb_type;
fbCmap = fbaddrs[whichFb].fb_cmap;
if ((whichFb != FBTYPE_SUN4COLOR) && (whichFb != FBTYPE_SUNFAST_COLOR) &&
(whichFb != FBTYPE_SUN3COLOR)) {
printf("Wrong fb type to have a colormap.\n");
return FAILURE;
}
/* Init colormap copy, overlay, etc.. */
if(whichFb == FBTYPE_SUNFAST_COLOR) {
fbCmap->addr = 0x06 << 24; /* command register address */
fbCmap->ctrl = 0x70 << 24; /* disable cursor overlay */
} else {
for (c = 0; c < 256 * 3 / 4; c++) {
fbCmapCopy.raw[c] = fbCmap->cmap;
}
fbCmap->addr = 0x06; /* command register address */
fbCmap->ctrl = 0x73; /* enable overlay */
/* set overlay colors: bg: blue, fg: white */
fbCmap->addr = 0x00;
fbCmap->omap = 0x00000000;
fbCmap->omap = 0x00ff0000;
fbCmap->omap = 0x00ffffff;
}
return SUCCESS;
}